/* 
 * File:   Solver.cpp
 * Author: Lucky
 * 
 * Created on 28. září 2011, 13:14
 * 
 * Solver představuje řešitele, který postupně prochází všechny možnosti
 * a zjišťuje, zda našl výsledek. Pokud solver najde řešení s K kroky, potom
 * již neprohledává řešení s větším či stejným počtem kroků
 */

#include <iostream>
#include <iomanip>
#include "Solver.h"
#include "Chessboard.h"
#include "LightStack.h"
#include "Library.h"
#include "Node.h"

Solver::Solver(Chessboard* board, LightStack* stack) {
    m_board = board;
    m_stack = stack;
    m_res = 0;
    m_stepCount = 0;
}

Solver::Solver(const Solver& orig) {
    throw "No solver copy constructor";
}

Solver::~Solver() {
    delete m_board;
    delete m_stack;
    if (m_res != 0) delete m_res;
}

void Solver::compute() {
    cout << "Pocitam " << endl;
    while (!(m_stack->isEmpty())) {

        Node* node = m_stack->pop();
        
        //Pokud byl již node popnut (odstraněn ze zasobniku), potom se vracime
        //ve stromu nahoru a pokud node zpusobil v ceste dolu sepnuti, musime
        //navratit stav opetovnym sepnutim. 
        //
        //Pokud ještě popnut nebyl, ale počet
        //již provedeních sepnutí je o jedem menší nebo větší než počet sepnutí
        //nejlepšího výsledku (node již nemuže přinést lepší výsledek), pak 
        //se také vrať nahoru
        if (node->isPopped()) {
            if (node->getAction() == SWITCH) {
                m_board->pressLight(node->x, node->y);
                --m_stepCount;
            }
            delete node;
            continue;
        } else if (m_res != 0 && m_res->getSteps() <= (m_stepCount + 1)) {
            m_stack->pop();
            delete node;
            continue;
        }

        int nextX = 0;
        int nextY = 0;
        Library::getNextCoordinate(node->x, node->y, m_board->getWidth(), &nextX, &nextY);
        if (Library::getCoordLength(m_board->getWidth(), nextX, nextY) < m_board->getSize()) {
            Node* child1 = new Node(nextX, nextY, SWITCH);
            Node* child2 = new Node(nextX, nextY, LEAVE);
            m_stack->push(child1);
            m_stack->push(child2);
        }
        //cout << "Pocet rozsvicenych svetel: " << m_board->getOnLightsCount() << endl;
        if (node->getAction() == SWITCH) {
            m_board->pressLight(node->x, node->y);
            ++m_stepCount;
            if (m_board->getOnLightsCount() == 0) {
                std::cout << "Mam lepsi reseni!" << m_stack->getLength() << std::endl;
                m_res = m_stack->getResult();
                std::cout << m_res->getSteps() << std::endl;
            }
        }
    }
    
    if (m_res != 0) m_res->printCoords();
}
